<p>Объекты: String, Map, Number - аналоги примитивов string, array, float+integer из PHP-Core</p>

<h1>Описание, Преимущества</h1>

<p>В отличии от большинства известных оберток(в том числе в отличии от встроенного ArrayObject), которые есть только "демонстрацией возможностей" и базируются на рефлексии и лени автора - данная библиотека создана для полной замены встроенных примитивов полноценными объектами.</p>

<p>Более логические и последовательные названия методов, порядок аргументов в них и возвращаемые значения, чем в встроенных функциях php (смотрите интерфейсы соответствующих объектов. Обратите внимание на, например <code>String::preg*()</code> методы)</p>

<p>Поддерживается цепочка вызовов с плавным переходом между объектами</p>

<pre><code>$map = new Map('a', 'b', 'c');
$map
    -&gt;join() // String object
    -&gt;add('def') // 'abcdef'
    -&gt;split(2) // Map object
    -&gt;length(); // Number object
</code></pre>

<p>Плавное "встраивание" в интерфейс заменяющее примитивы в таких переменных, как <code>$GLOBALS</code>, <code>$_POST</code> и т.п. на соответствующие объекты:</p>

<pre><code>Map::found(); // Основаться
$GLOBALS-&gt;dump();
</code></pre>

<p>Позволяет работать с объектами и как с примитивами и как с объектами (тем не менее, нельзя забывать, что объекты передаются по ссылке, тогда как массивы копируются, из-за чего может быть несущественное отличие в поведении):</p>

<pre><code>$map = new Map('a', 'b', 'c');
foreach ($map as $val) {
    echo $val; // 'abc'
}
while($map-&gt;each($val)) {
    echo $val; // 'abc'
}
</code></pre>

<p>Имеется встроенный объект для создания дампа объектов (аналог var_dump), который не выводит лишнюю информацию о данных объектах как встроенные аналоги, и метод dump() у каждого из объектов, чтобы можно было получить значение объекта не выходя из цепочки:</p>

<pre><code>Map::create('a', 'b', 'c')
    -&gt;join(',')
    -&gt;dump()
    -&gt;replace('b', 'e')
    -&gt;dump();

/**
(String) 'a,b,c'
(String) 'a,e,c'
*/

echo new Dump($somevar); // Если мы не знаем, каким объектом будет $somevar
</code></pre>

<p>Возможность создания объекта через статический метод, или функцию для того, чтобы сразу начать работать с цепочкой:</p>

<pre><code>$map = String::create('def')
  -&gt;insert('abc ')
  -&gt;changeCase(Str::TITLE, Str::UP_FORCED)
  -&gt;split()
  -&gt;dump();

$map = o('def')
  -&gt;insert('abc ')
  -&gt;changeCase(Str::TITLE, Str::UP_FORCED)
  -&gt;split()
  -&gt;dump();
/**
Map [
    0 : 'A'
    1 : 'b'
    2 : 'c'
    3 : ' '
    4 : 'D'
    5 : 'e'
    6 : 'f'
]
 */
</code></pre>

<p>Все методы, которые должны работать с примитивами - одинаково хорошо работают что с примитивами, что с их объектными аналогами:</p>

<pre><code>o('a', 'b')
  -&gt;merge(
    new Map('c', 'd'),
    array('e', 'f'),
    'g', new String('h')
  )
  -&gt;dump();
/**
Map [
    0 : 'a'
    1 : 'b'
    2 : 'c'
    3 : 'd'
    4 : 'e'
    5 : 'f'
    6 : 'g'
    7 : (String) 'h'
]
*/
</code></pre>

<p>Экземпляр объекта Map содержит в себе примитивы, или объекты - зависимо от того, что передать объекту, а подменяет примитивы на соответствующие объекты только при надобности (для того, чтобы не делать лишней работы). Кроме маленьких пометок во время Dump'a на работу конечного пользователя никак не влияет данный ньюанс - все выходные данные есть либо объектами, либо типами, которые не предусмотренны данной библиотекой (например, bool). (<em>См. предыдущий пример</em>)</p>

<p>Позволяет реализовать практически полноценный [http://us2.php.net/manual/en/language.oop5.typehinting.php typehinting], что нельзя реализовать при использовании примитивов:</p>

<pre><code>function testTypeHinting (Number $num) {
    return $num-&gt;root(5);
}

$num = new Number (15);
$str = new String ('test');

   testTypeHinting($num)-&gt;dump(); // (Number) 1.71877192759
// testTypeHinting($str)-&gt;dump(); // Catchable fatal error
</code></pre>

<p>От данных объектов можно наследовать другие объекты, которые будут реализовывать расширенный функционал, или специальную логику, сохранив при этом функционал родительского класса</p>

<p>Встроенный конвертер величин, поддерживающий группировку:</p>

<pre><code>// Сколько байт в 300 гигабайтах?
echo o(300)-&gt;convert('Bytes', 'GiB', 'B'), "\n"; // 322122547200
// Сколько секунд в 3 сутках?
echo o(3)  -&gt;convert('Time', 'Day', 'Second'), "\n";  // 259200
// Сколько метров в одной морской миле?
echo o(1)  -&gt;convert('Length', 'SeaMile', 'Metr'), "\n"; // 1852
</code></pre>

<p>Вместе с возможностью наследования позволяет делать очень полезные вещи (в примере видна группировка через точку):</p>

<pre><code>// Смотрите «KurrencyKonverter.php» в «examples»
$uah = new KurrencyKonverter (500);
// Сколько долларов у нас будет, если мы купим их в Украине за 500 гривень
echo $uah
    -&gt;copy()
    -&gt;convert('Currency.Ua.Sell', 'UAH', 'USD')
    -&gt;toString(2); // 63,02
// Сколько долларов у нас будет, если мы купим в Украине за 500 гривень рубли, а потом в России за эти же рубли - доллары
echo $uah
    -&gt;convert('Currency.Ua.Sell', 'UAH', 'RUR')
    -&gt;convert('Currency.Ru'     , 'RUR', 'USD')
    -&gt;toString(2); // 44,77
</code></pre>

<p>Поддерживает последние актуальные версии php и их особенности, например замыкания (closures). При этом, возможность их использовать совершенно не мешает для более молодых версий этого языка:</p>

<pre><code>$n = new Number(115);
if($n-&gt;match(function ($t) {
    return ($t-&gt;root(3)-&gt;gt(5)); // Если кубический корень числа больше 5 - истина, иначе - ложь
})) {
    echo '$n is greater than 125', "\n";
} else {
    echo '$n is smaller or equal than 125', "\n";
}

$s = new String("Some string with number(e.g. 12345), is here");
echo o($s)-&gt;replace(array('string', 'number'), function ($r) {
    return $r-&gt;changeCase(Str::ALL, Str::RANDOM); 
}); // Some sTrINg with NuMbEr(e.g. 12345), is here
echo "\n";


o(1, 4, 7, 9, 15)-&gt;clear(function ($key, $value) {
    if ($key == 0) {
        return true; // Элемент с ключем равным 0 оставляем независимо от значение
    }
    if ($value &gt; 6 and $value &lt; 13) {
        return true;  // Оставить только значения между 6 и 13
    } else {
        return false; // Все остальное убить
    }
})-&gt;dump(); // [7, 9];


// Метод сам определит - здесь лямбдда функция, или обычный параметр (например, строка, или объект String):
echo o($s)-&gt;pregReplace("/([0-9]+)/", function ($m) {
    return "!$m[0]!"; // Some string with number(e.g. !12345!), is here
});        
echo "\n";


// Для более старых версий все-еще поддерживается старый синтаксис:
echo o($s)-&gt;pregReplaceCallback("/([0-9]+)/", create_function('$m',
    'return "!$m[0]!";' // Some string with number(e.g. !12345!), is here
));
</code></pre>

<p>Ну и вспомним Руби :) Конечно, не так изящно, как в оригинале, но, согласитесь, своя романтика в этом есть.</p>

<pre><code>o(5)-&gt;times(function ($i) use ($n) {
    echo ($i-&gt;isEven()) ? "Even: " : "Odd : ";
    echo $n , "." , $i , ";\n";
});
/*
Even: 5.0;
Odd : 5.1;
Even: 5.2;
Odd : 5.3;
Even: 5.4;
*/
</code></pre>

<h1>Недостатки</h1>

<p>Возможно уменьшение скорости работы методов в ~1-3 раза по сравнению с core-функциями (зависимо от объема данных - чем больше объем - тем меньше увеличение времени), но учитывая, что вызов core-функций обычно(тем более, с малыми переданными объемами) - это лишь крохи в сравнении с временем затраченным на выполнение запросов - общее увеличение времени выполнения работы скрипта будет незначительным (на 1-5%). </p>

<h1>Расширенный пример</h1>

<p><em>Данный пример стоит детальнее посмотреть в браузере</em></p>

<pre><code>Map::found();
$GLOBALS-&gt;dump();

class Test {
    public    $beerpub = 123;
    protected $protos  = 234.543;
    private   $vipriv  = array ();
    private   $array = array();

    public function __construct () {
        $this-&gt;vipriv['this'] = $this;
        $this-&gt;vipriv['str']  = new String ('privStr');
        $this-&gt;vipriv['int']  = new Number (13);
    }
}

$map = Map::create(
        new String ('test'),
        new Number (14),
        new Map ('aaa', 'bbb'),
        new Test ()
    )
    -&gt;merge(
        array ('value1', 'key'=&gt;'value2'),
        'String',
        123
    )
    -&gt;dump()
    -&gt;remove(3)
    -&gt;join(',', 1) // String
    -&gt;split(8) // Map
    -&gt;dump();
$map-&gt;reset();
$newMap = new Map;
while ($map-&gt;each($key, $value)) {
    if (mt_rand(0, 1)) {
        $newMap[] = $value;
    }
}
$newMap
    -&gt;join(' ') // String
    -&gt;replace(',', 'зпт')
    -&gt;changeCase(Str::TITLE, Str::UP_FORCED)
    -&gt;insert('[вставлено]', 5)
    -&gt;length() // Number
    -&gt;multiply(4)
    -&gt;add(6, 9, new Number(15))
    -&gt;divided(5)
    -&gt;sum(Number::EVEN)
    -&gt;dump() // (Number) 1062.51
    -&gt;root(4)
    -&gt;round(3) // Just 3 symbols after dot
    -&gt;dump() // (Number) 5.709
    -&gt;round(Number::UP) // round to up (ceil)
    -&gt;hex('15abbf')
    -&gt;toString() // String ('1420223')
    -&gt;hash() // 'md5' as default
    -&gt;dump(); // (String) '0d1b1558224c8f3b125cd905c378c9f7'
</code></pre>

<h1>Зависимости</h1>

<p>Необязательны интерфейсы (предоставлены в ознакомительных целях). Можете убить, не забыв при этом удалить из объявления классов.</p>

<h1>Подключение</h1>

<p>Require всех файлов библиотеки</p>

<h1>Требования</h1>

<p>Желательна последняя версия PHP. Минимум - пятая. При недостаточно высокой версии могут не работать некоторые методы (например, метод hash для php &lt; 5.1.2 может работать некорректно для нестандартных алгоритмов (все, кроме "md5", "sha1", "crc32")</p>

<h1>Подробнее</h1>

<p>В коде и интерфейсах</p>
